
#include "Epoll_Accept.h"


Epoll_Accept_Conf::Epoll_Accept_Conf()
{
    m_nMax_epollfd_size = 600;
    m_nMax_info_size = 1200;
    m_nOn_off = 1;
    m_sServerEvent.events = EPOLLIN | EPOLLET;
    m_nEpollfd = epoll_create(m_nMax_epollfd_size);
}

Client_Info::Client_Info()
{
    client_len = sizeof(struct sockaddr_in);
}

Accept_Info::Accept_Info()
{
    event = -1;
    client_fd = -1;
    server_fd = -1;
    epoll_fd = -1;
}

///
/// class part
///


Epoll_Accept::Epoll_Accept(int aServerSocketfd)
{
    m_sConf.m_sServerEvent.data.fd = aServerSocketfd;
    init();
}

Epoll_Accept::Epoll_Accept(struct Epoll_Accept_Conf a_sConf)
{
    m_sConf = a_sConf;
    init();
}
/**
 *  init variable.
 */
int Epoll_Accept::init()
{
    m_pIPC_mmap = new MMAP_IO<Accept_Info>();
    char filepath[] = "./epoll_accept.in";
    m_pIPC_mmap->initFd(filepath);
    m_pIPC_mmap->initSpace(10);
    m_pIPC_mmap->initPtr(0);
    return SERVER_DEFAULT_SUCCESS;
}

/**
 * configure epoll，create epollfd，epoll_ctl--configure epoll event
 */
int Epoll_Accept::Configure()
{
    // place epoll_ctl's return num, use for return
    int _result = 0;
    
    _result = epoll_ctl(m_sConf.m_nEpollfd, EPOLL_CTL_ADD, m_sConf.m_sServerEvent.data.fd, &(m_sConf.m_sServerEvent));
    
    if (_result < 0)
    {
        fprintf(stderr, "epoll set insertion error: fd=%d :::Errno:%s \n ", m_sConf.m_sServerEvent.data.fd, strerror(errno));
    }
    else
    {
        fprintf(stdout, ":::Server Socket is binded successed ... epollfd:%d, socketfd:%d \n", m_sConf.m_nEpollfd, m_sConf.m_sServerEvent.data.fd);
    }
    
    return _result;
}


int Epoll_Accept::Listening()
{
    // the event's num with one listen
    int _eventNum = 0;
    // use for ctl client.
    struct epoll_event _ev;
    // place all coming events in one time
    struct epoll_event *_events = new epoll_event[m_sConf.m_nMax_epollfd_size];
    // listening cycle..
    while (m_sConf.m_nOn_off)
    {
        printf(":::One Waiting ... \n");
        // listening
        _eventNum = epoll_wait(m_sConf.m_nEpollfd, _events, m_sConf.m_nMax_epollfd_size, -1);
        
        if (_eventNum == -1) {
            fprintf(stderr, "epoll_wait error :::Errno:%s \n ", strerror(errno));
            continue;
        }
        
        for(int i = 0; i < _eventNum; i++)
        {
            int _catched_fd = _events[i].data.fd;
            switch (_events[i].events)
            {
                fprintf(stdout, ":::DISPACH Event is: %d\n", _events[i].events);
                case EPOLLIN:
                    if(_catched_fd == m_sConf.m_sServerEvent.data.fd)
                    {   
                        //fprintf(stdout, ":::ACCEPT ArraySize is : %d\n", m_pInfo_Array->size());
                        fprintf(stdout, ":::ACCEPT fd is: %d\n", _catched_fd);
                        // save coming connect's fd
                        int _new_fd;
                        // client info
                        Client_Info _client_info;
                        // coming fd
                        _new_fd = accept(_catched_fd, (struct sockaddr*)&_client_info.client_addr, &_client_info.client_len);
                        
                        if(_new_fd < 0)
                        {
                            fprintf(stderr, "_new_fd < 0 : fd=%d :::Errno:%s \n ", _new_fd, strerror(errno));
                        }
                        else
                        {
                            fprintf(stdout, ":::A New Connect,IP:%s:%d fd:%d\n", inet_ntoa(_client_info.client_addr.sin_addr), ntohs(_client_info.client_addr.sin_port), _new_fd);
                            
                            setNonblocking(_new_fd);
                            // deploy the new fd's epoll attribute
                            _ev.events = EPOLLIN | EPOLLET;
                            _ev.data.fd = _new_fd;
                            
                            if(epoll_ctl(m_sConf.m_nEpollfd, EPOLL_CTL_ADD, _new_fd, &_ev) < 0)
                            {
                                fprintf(stderr, "ctl client newfd error: fd=%d :::Errno:%s \n ", _new_fd, strerror(errno));
                            }
                            
                            Accept_Info* _acceptOne = new Accept_Info();
                            _acceptOne->client_fd = _new_fd;
                            _acceptOne->server_fd = m_sConf.m_sServerEvent.data.fd;
                            _acceptOne->epoll_fd = m_sConf.m_nEpollfd;
                            _acceptOne->event = 1;
                            
                            m_pIPC_mmap->memwrite(_acceptOne);
                            //m_pIPC_mmap->memsync();
                            //m_pIPC_mmap->menunmap();
                        }  
                    }
                    else
                    {
                        fprintf(stdout, ":::RECIVE fd is: %d\n", _catched_fd);
                        //fprintf(stdout, ":::READ ArraySize is : %d\n", m_pInfo_Array->size());
                        char buf[1024 + 1];
                        int _len;
                        /* 开始处理每个新连接上的数据收发 */
                        bzero(buf, 1024 + 1);
                        printf("errno:%s\n", strerror(errno));
                        do{
                            /* 接收客户端的消息 */
                            _len = recv(_catched_fd, buf, 1024, 0);
                            
                            printf("_len= %d,Recving.. errno:%s\n", _len, strerror(errno));
                            
                        }while(errno != EAGAIN);
                        
                        if (_len > 0 || (_len < 0 && errno == EAGAIN))
                        {
                            printf("fd:%d 接收消息成功:\n%s \n 共%d个字节的数据\n",
                                  _catched_fd, buf, _len);
                            
                            
                            
                            
                            
                            
                            
                            int t_len = write(_catched_fd, buf, strlen(buf));
                            
                            fprintf(stdout, "send len: %d \n ", t_len);
                            
                         }
                        else
                         {
                            if (_len < 0 || _len == 0)
                                 printf
                                     ("消息接收失败！len= %d,错误代码是%d，错误信息是'%s'\n", _len,
                                      errno, strerror(errno));
                         }
                    }
                    break;
                case EPOLLOUT:
                    printf("一次OUT！errno代码是%d，strerrno是'%s'\n", errno, strerror(errno));
                    break;
            }
            
        }
        
    }
    
    return SERVER_PROCESS_QUIT;
}

int Epoll_Accept::MMAP_OUT(struct Accept_Info* a_infoStruct)
{   
    m_pIPC_mmap->memwrite(a_infoStruct);
    
    printf("Send One \n");
    
    m_pIPC_mmap->memsync();
    //mmao_io->menunmap();
    return SERVER_DEFAULT_SUCCESS;
}




